// 借助打包工具，将代码处理成浏览器能够解析的代码

// (1)获取入口文件代码
const fs = require('fs');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const path = require('path');
const babel = require('@babel/core');
// const depsGraph = require('@deps-graph');

// const getModuleInfo = (file) => {
//     const body = fs.readFileSync(file, 'utf-8');
//     // console.log(body);解析前

//     const ast = parser.parse(body, {
//         sourceType: 'module'
//     })

//     // console.log(ast);解析后
//     // console.log(ast.program.body);

//     // 遍历AST（收集所需路径依赖）
//     const deps = {};
//     traverse(ast, {
//         // 对某个node对象进行ImportDeclaration处理
//         ImportDeclaration({ node }) {
//             const dirname = path.dirname(file);
//             const abspath = './' + path.join(dirname, node.source.value)
//             deps[node.source.value] = abspath
//         }
//     })

//     // 根据抽象语法树生成浏览器可运行的代码，将现有语法树转换为es5
//     const { code } = babel.transformFromAst(ast, null, {
//         presets: ["@babel/preset-env"]
//     })
//     // console.log(deps);
//     // console.log(code);

//     // 将所有关于同一个文件(./src/index.js)的依赖(file,deps,code)全部放到一起(moduleInfo)
//     const moduleInfo = { file, deps, code }
//     return moduleInfo
// }

// const parseModules = (file) => {
//     const entry = getModuleInfo(file);
//     const temp = [entry]
//     for (let i = 0; i < temp.length; i++) {
//         const deps = temp[i].deps
//         if (deps) {//deps:{ './add.js': './src\\add.js', './minus.js': './src\\minus.js' }{ './add.js': './src\\add.js', './minus.js': './src\\minus.js' }
//             for (let key in deps) {
//                 if (deps.hasOwnProperty(key)){//true  显示具备的属性；false 有原型链上的东西
//                     temp.push(getModuleInfo(deps[key]))
//                 }
//             }
//         }
//     }
//     console.log(temp);
// }

const getModuleInfo = (file) => {
    const body = fs.readFileSync(file, 'utf-8');
    const AST = parser.parse(body, {
        sourceType: 'module'
    })

    const deps = {}
    traverse(AST, {
        ImportDeclaration({
            node
        }) {
            const dirname = path.dirname(file)
            const abspath = './' + path.join(dirname, node.source.value)
            deps[node.source.value] = abspath
        }
    });

    const {
        code
    } = babel.transformFromAst(AST, null, {
        presets: ['@babel/preset-env'],
    });

    const moduleInfo = {
        file,
        deps,
        code
    }
    return moduleInfo
}

const parseModules = (file) => {
    const entry = getModuleInfo(file)
    const temp = [entry]
    for (let i = 0; i < temp.length; i++) {
        let deps = temp[i].deps
        if (deps) {
            for (let key in deps) {
                if (deps.hasOwnProperty(key)) {
                    const res = getModuleInfo(deps[key])
                    temp.push(res)
                }
            }
        }
    }
    console.log(temp);
    temp.forEach(moduleInfo => {
        depsGraph[moduleInfo.file] = {
            deps: moduleInfo.deps,
            code: moduleInfo.code
        }
    })

    return depsGraph;
}

// 将多份代码整理到一起
const bundle = (file) => {
    const depsGraph = JSON.stringify(parseModules(file))
    return `(function(graph){
        function require(file) {
          function absRequire(relPath) {
            return require(graph[file].deps[relPath])
          }
          var exports = {}
          (function(require, exports, code) {
            eval(code)
          })(absRequire, exports, graph[file].code)
          return exports
        }
        require(${file})
      })(${depsGraph})`
}
const content = bundle('./src/index.js')
console.log(content);

fs.mkdirSync('./dist')
fs.writeFileSync('./dist/main.js', content)